﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Odelle.Utils.Comparisons
{
    public class FlexibleNumberComparator:NumberComparator
    {
        public static char Delimiter { get { return '\\'; } }

        /// <summary>
        /// compare the value with parse values of formatValue 
        /// </summary>
        /// <param name="value">number</param>
        /// <param name="formatValue">values, delimiter="\", like">=100/<=500"</param>
        /// <returns></returns>
        public override bool Compare(int value, string formatValue)
        {
            string[] fValue = splitFormatValue(formatValue);

            int fv = 0;
            bool result = true;

            for (int i = 0; i < fValue.Length; i += 2)
            {
                if (fValue[i + 1] != "*")
                {
                    result = result && int.TryParse(fValue[i + 1], out fv);

                    switch (fValue[i])
                    {
                        case "=":
                            result = result && (value == fv);
                            break;
                        case ">=":
                            result = result && (value >= fv);
                            break;
                        case ">":
                            result = result && (value > fv);
                            break;
                        case "<=":
                            result = result && (value <= fv);
                            break;
                        case "<":
                            result = result && (value < fv);
                            break;
                        default:
                            result = false;
                            break;
                    }

                    if (!result)
                        break;
                }
            }

            return result;
        }

        /// <summary>
        /// compare the value with parse values of formatValue 
        /// </summary>
        /// <param name="value">number</param>
        /// <param name="formatValue">values, delimiter="\", like">=100/<=500"</param>
        /// <returns></returns>
        public override bool Compare(long value, string formatValue)
        {
            string[] fValue = splitFormatValue(formatValue);

            long fv = 0;
            bool result = true;

            for (int i = 0; i < fValue.Length; i += 2)
            {
                if (fValue[i + 1] != "*")
                {
                    result = result && long.TryParse(fValue[i + 1], out fv);

                    switch (fValue[i])
                    {
                        case "=":
                            result = result && (value == fv);
                            break;
                        case ">=":
                            result = result && (value >= fv);
                            break;
                        case ">":
                            result = result && (value > fv);
                            break;
                        case "<=":
                            result = result && (value <= fv);
                            break;
                        case "<":
                            result = result && (value < fv);
                            break;
                        default:
                            result = false;
                            break;
                    }

                    if (!result)
                        break;
                }
            }

            return result;
        }

        /// <summary>
        /// compare the value with parse values of formatValue 
        /// </summary>
        /// <param name="value">number</param>
        /// <param name="formatValue">values, delimiter="\", like">=100/<=500"</param>
        /// <returns></returns>
        public override bool Compare(float value, string formatValue)
        {
            string[] fValue = splitFormatValue(formatValue);

            float fv = 0F;
            bool result = true;

            for (int i = 0; i < fValue.Length; i += 2)
            {
                if (fValue[i + 1] != "*")
                {
                    result = result && float.TryParse(fValue[i + 1], out fv);

                    switch (fValue[i])
                    {
                        case "=":
                            result = result && (value == fv);
                            break;
                        case ">=":
                            result = result && (value >= fv);
                            break;
                        case ">":
                            result = result && (value > fv);
                            break;
                        case "<=":
                            result = result && (value <= fv);
                            break;
                        case "<":
                            result = result && (value < fv);
                            break;
                        default:
                            result = false;
                            break;
                    }

                    if (!result)
                        break;
                }
            }

            return result;
        }

        /// <summary>
        /// compare the value with parse values of formatValue 
        /// </summary>
        /// <param name="value">number</param>
        /// <param name="formatValue">values, delimiter="\", like">=100/<=500"</param>
        /// <returns></returns>
        public override bool Compare(double value, string formatValue)
        {
            string[] fValue = splitFormatValue(formatValue);

            double fv = 0.0;
            bool result = true;

            for (int i = 0; i < fValue.Length; i += 2)
            {
                if (fValue[i + 1] != "*")
                {
                    result = result && double.TryParse(fValue[i + 1], out fv);

                    switch (fValue[i])
                    {
                        case "=":
                            result = result && (value == fv);
                            break;
                        case ">=":
                            result = result && (value >= fv);
                            break;
                        case ">":
                            result = result && (value > fv);
                            break;
                        case "<=":
                            result = result && (value <= fv);
                            break;
                        case "<":
                            result = result && (value < fv);
                            break;
                        default:
                            result = false;
                            break;
                    }

                    if (!result)
                        break;
                }
            }

            return result;
        }

        /// <summary>
        /// compare the value with parse values of formatValue 
        /// </summary>
        /// <param name="value">number</param>
        /// <param name="formatValue">values, delimiter="\", like">=100/<=500"</param>
        /// <returns></returns>
        public override bool Compare(DateTime value, string formatValue)
        {
            string[] fValue = splitFormatValue(formatValue);

            DateTime fv = DateTime.Now;
            bool result = true;

            for (int i = 0; i < fValue.Length; i += 2)
            {
                if (fValue[i + 1] != "*")
                {
                    result = result && DateTime.TryParse(fValue[i + 1], out fv);

                    value = value.Date;
                    fv = fv.Date;

                    switch (fValue[i])
                    {
                        case "=":
                            result = result && (value == fv);
                            break;
                        case ">=":
                            result = result && (value >= fv);
                            break;
                        case ">":
                            result = result && (value > fv);
                            break;
                        case "<=":
                            result = result && (value <= fv);
                            break;
                        case "<":
                            result = result && (value < fv);
                            break;
                        default:
                            result = false;
                            break;
                    }

                    if (!result)
                        break;
                }
            }

            return result;
        }
        private string[] splitFormatValue(string formatValue)
        {
            string[] splits = formatValue.Split( FlexibleNumberComparator.Delimiter);
            List<string> results = new List<string>();

            for (int i = 0; i < splits.Length; ++i)
            {
                if (splits[i].StartsWith("=="))
                {
                    results.Add("=");
                    results.Add( splits[i].Replace("==", ""));
                }
                else if (splits[i].StartsWith("="))
                {
                    results.Add("=");
                    results.Add( splits[i].Replace("=", ""));
                }
                else if (splits[i].StartsWith(">="))
                {
                    results.Add(">=");
                    results.Add( splits[i].Replace(">=", ""));
                }
                else if (splits[i].StartsWith(">"))
                {
                    results.Add(">");
                    results.Add( splits[i].Replace(">", ""));
                }
                else if (splits[i].StartsWith("<="))
                {
                    results.Add("<=");
                    results.Add(splits[i].Replace("<=", ""));
                }
                else if (splits[i].StartsWith("<"))
                {
                    results.Add("<");
                    results.Add(splits[i].Replace("<", ""));
                }
                else
                {
                    results.Add("=");
                    results.Add(splits[i]);
                }
            }

            return results.ToArray();
        }
    }
}
